import { DBManagerComponent } from "../../../../Model/Server/Module/DB/DBManagerComponent";
import { ObjectSystemAttribute, FriendOf, ExpandOf } from "../../../../../Decorator/Decorator";
import { AwakeSystem } from "../../../../../Core/Module/EventSystem/IAwakeSystem";
import { DestroySystem } from "../../../../../Core/Module/EventSystem/IDestroySystem";
import { DBComponent } from "../../../../Model/Server/Module/DB/DBComponent";
import { Exception } from "../../../../../Core/Object/Exception";
import { StartZoneConfigCategory } from "../../../../Model/Generate/Server/Config/StartZoneConfig";
import { Entity } from "../../../../../Core/Module/Entity/Entity";
import { WithId } from "mongodb";
import { MongoHelper } from "../../../../../Core/Serialize/MongoHelper";

/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "../../../../Model/Server/Module/DB/DBManagerComponent" {

    interface DBManagerComponent {
        GetZoneDB(zone: number): Promise<DBComponent>;
        GetEntity<T extends Entity>(clazz: typeof Entity, data: WithId<T>): T;
    }

}

@ExpandOf(DBManagerComponent)
export class DBManagerComponentSystem {

    private static async GetZoneDB(self: DBManagerComponent, zone: number): Promise<DBComponent> {
        let dbComponent = self.DBComponents[zone];
        if (dbComponent != null) {
            return dbComponent;
        }
        let startZoneConfig = StartZoneConfigCategory.Instance.Get(zone);
        if (startZoneConfig.DBConnection == "") {
            throw new Exception(`zone: ${zone} not found mongo connect string`);
        }
        dbComponent = await self.AddChild<DBComponent, string, string, number>(DBComponent, startZoneConfig.DBConnection, startZoneConfig.DBName, zone).Connect();
        self.DBComponents[zone] = dbComponent;
        return dbComponent;
    }

    private static GetEntity<T extends Entity>(self: DBManagerComponent, clazz: typeof Entity, data: WithId<T>): T {
        let entity = self.AddChild<T>(clazz);
        self.RemoveChild(entity.Id);
        MongoHelper.FromBson(entity, data);
        return entity;
    }

}

@FriendOf(DBManagerComponent)
@ObjectSystemAttribute()
export class DBManagerComponentAwakeSystem extends AwakeSystem<DBManagerComponent> {

    Awake(self: DBManagerComponent): void {
        DBManagerComponent.Instance = self;
    }

}

@FriendOf(DBManagerComponent)
@ObjectSystemAttribute()
export class DBManagerComponentDestroySystem extends DestroySystem<DBManagerComponent> {

    Destroy(self: DBManagerComponent): void {
        DBManagerComponent.Instance = null;
    }

}